package creational_pattern.singleton_pattern;

/**
 * @version: 1.0
 * @Description: TODO
 * @author: zZmH
 * @date: 2020/10/27 18:23
 */


public class Singleton {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, CloneNotSupportedException {
        Object o = Object.class.newInstance();
        Singleton singleton = Singleton.class.newInstance();
        Singleton sz = (Singleton) singleton.clone();


    }
    /*1.饿汉
     类加载的时候就创建了实例
    优点：类加载的时候创建一次实例，避免了多线程同步问题
    缺点：即使单例没被用到也会创建，浪费内存
     **/
    static class HungryMan{
        private static HungryMan singleton = new HungryMan();

        public static HungryMan getInstance() {
            return singleton;
        }
    }

    //2.懒汉-（非线程安全）
    //优点：需要时才去创建
    //缺点：没有考虑线程安全问题，多个线程并发调用getInstance，可能会创建多个实例
    static class LazyManNotSafe{
        private LazyManNotSafe singleton = null;
        private LazyManNotSafe(){
        }
        public LazyManNotSafe getInstance(){
            if (singleton == null) {
                singleton = new LazyManNotSafe();
            }
            return singleton;
        }
    }

    //3.双重校验锁
    //大部分情况下，同步代码块都不会执行到，提高了程序的性能。
    //
    //有一种情况，两个线程ThreadA，ThreadB，
    // 如果threadA执行到了第一个if条件判断，instance = null；ThreadB也执行到了if条件判断instance = null，
    // 所以A和B会依次执行同步代码块里的代码。为了避免创建两个实例，因此又在同步代码块里添加了if条件进行二重检验。
    static class LazyManSafe{
        private LazyManSafe(){}
        private static volatile LazyManSafe singleton = null;

        public static LazyManSafe getInstance(){
            if (singleton == null) {
                synchronized (LazyManSafe.class) {
                    if (singleton == null) {
                        singleton = new LazyManSafe();
                    }

                }
            }
            return singleton;
        }
    }

    //4.静态内部类
    static class StaticInner{
        private StaticInner(){}
        static class Inner{
            private static StaticInner singleton = new StaticInner();
        }

        public static StaticInner getInstance() {
            return Inner.singleton;
        }
    }

    //5.枚举
   static class EnumSingleton{
        private EnumSingleton(){}

        public static EnumSingleton getInstance() {
            return InnerEnum.INSTANCE.getInstance();
        }
        private static enum InnerEnum{
            INSTANCE;
            private EnumSingleton singleton;
            private InnerEnum(){
                singleton = new EnumSingleton();
            }
            public EnumSingleton getInstance(){
                return singleton;
            }
        }

    }




}
